package Arcsight::Event;

use strict;

use Text::Table;

sub new {
	my ($class,%parms) = @_;
	my $self = {};
	bless($self,$class);

	# set the default params
	$self->details(	$parms{'-details'});
	$self->id(	$parms{'-id'});
	$self->cases(	$parms{'-cases'}) if(defined($parms{'-cases'}));
	return($self);
}

sub id {
	my ($self,$v) = @_;
	$self->{_id} = $v if(defined($v));
	return $self->{_id};
}

sub cases {
	my ($self,$v) = @_;
	if(defined($v) && uc(ref($v)) eq 'ARCSIGHT::CASE'){
		$self->{_cases}->{$v->id()} = $v;
	}
	return $self->{_cases};
}

sub baseEvents {
	my ($self,$v) = @_;
	if(defined($v) && uc(ref($v)) eq 'ARCSIGHT::EVENT'){
		$self->{_baseEvents}->{$v->id()} = $v;
	}
	return($self->{_baseEvents});
}

sub details {
	my ($self,$v) = @_;
	$self->{_details} = $v if(defined($v));
	return($self->{_details});
}

sub IODEF {
	my $self = shift;
	return(undef) unless($self->details());
	my $iodef = XML::IODEF->new();
	my $details = $self->details();

	$iodef->add('IncidentIncidentDataExpectationDescription','need-to-know');
	$iodef->add('IncidentIncidentDataDescription',$details->{'fileName'} || $details->{'name'});
	$iodef->add('IncidentIncidentDataAssessmentImpactseverity',lc($details->{'agentSeverity'}));
	
	my $addr = $details->{'sourceAddress'} || $details->{'destinationAddress'};
	$iodef->add('IncidentIncidentDataEventDataSystemNodeAddressaddress',$addr) if($addr);

	$iodef->add('IncidentIncidentDataEventDataSystemServiceprotocol',$details->{'transportProtocol'}) if($details->{'transportProtocol'});
	$iodef->add('IncidentIncidentDataEventDataSystemServiceport','target/'.$details->{'destinationPort'}) if($details->{'destinationPort'});

	# TODO -- ensure UTC, set to UTC if not
	$iodef->add('IncidentIncidentDataDetectTime',$details->{'deviceReceiptTime'});
	$iodef->add('IncidentIncidentDataStartTime',$details->{'startTime'});
	$iodef->add('IncidentIncidentDataEndTime',$details->{'endTime'});

	my $confidence = 'low';
	$confidence = 'medium' if($details->{'modelConfidence'} > 5);
	$confidence = 'high' if($details->{'modelConfidence'} >= 9);
	$iodef->add('IncidentIncidentDataEventDataAssessmentConfidencerating',$confidence);	
	## TODO -- IDMEF Event objects? check new IODEF RFC from 2008 with EventData class
	if($self->baseEvents()){
		my $msg = '';
		my @sort = sort { $a <=> $b } keys(%{$self->baseEvents()});
		
		my $table = Text::Table->new('|','Date/Time','|','Type','|','Device','|','Rule','|');
		
		foreach my $event (@sort){
			
			my $d = $self->baseEvents->{$event}->details();
			$table->load(['|',$d->{'startTime'},'|',$d->{'device'}->{'map'}->{'product'},'|',$d->{'device'}->{'map'}->{'hostName'},'|',$d->{'name'},'|']);
		}
		
		$msg .= "\n\n".$table;
		
		$table = Text::Table->new('|','Date/Time','|','Protocol','|','Source','|','Destination','|');
		
		foreach my $event (@sort){
			my $d = $self->baseEvents->{$event}->details();
			my $startTime			= $d->{'StartTime'} || '';
			my $transportProtocol		= $d->{'transportProtocol'} || '';
			my $sourceAddress		= $d->{'sourceAddress'} || '';
			my $sourcePort			= $d->{'sourcePort'} || '';
			my $destinationAddress		= $d->{'destinationAddress'} || '';
			my $destinationPort		= $d->{'destinationPort'} || '';
			
			$table->load(['|',$startTime,'|', $transportProtocol,'|',$sourceAddress.':'.$sourcePort,'|', $destinationAddress.':'.$destinationPort,'|']);
		}
		
		$msg .= "\n\n".$table;
		
		$table = Text::Table->new('|','Date/Time','|','Protocol','|','Source','|','Destination','|');
		
		foreach my $event (@sort){
			my $d = $self->baseEvents->{$event}->details();
			
			my $src			= $d->{'sourceHostName'} || $d->{'sourceAddress'};
			my $dst			= $d->{'destinationHostName'} || $d->{'destinationAddress'};
			my $srcPort		= $d->{'sourcePort'} || '';
			my $dstPort		= $d->{'destinationPort'} || '';
			
			$table->load(['|',$d->{'StartTime'},'|', $d->{'transportProtocol'},'|',$src.':'.$srcPort,'|', $dst.':'.$dstPort,'|']);
		}
		
		$msg .= "\n\n".$table;
		
		$table = Text::Table->new('|','Date/Time','|','Source Country','|','Source Region','|','Source Location','|','Destination Country','|','Destination Region','|','Destination Area','|');
		
		foreach my $event (@sort){
			my $d = $self->baseEvents->{$event}->details();
			
			my $srcC = $d->{'sourceGeo'}->{'map'}->{'countryCode'} || 'NA';
			my $srcL = $d->{'sourceGeo'}->{'map'}->{'locationInfo'} || 'NA';
			my $srcR = $d->{'sourceGeo'}->{'map'}->{'regionCode'} || 'NA';
			
			my $dstC = $d->{'destinationGeo'}->{'map'}->{'countryCode'} || 'NA';
			my $dstL = $d->{'destinationGeo'}->{'map'}->{'locationInfo'} || 'NA';
			my $dstR = $d->{'destinationGeo'}->{'map'}->{'regionCode'} || 'NA';
			
			$table->load(['|',$d->{'startTime'},'|', $srcC,'|',$srcR,'|',$srcL,'|',$dstC,'|', $dstR, '|',$dstL,'|']);
		}
		
		$msg .= "\n\n".$table;		
		$iodef->add('IncidentIncidentDataEventDataAdditionalData',$msg);
	}

	return($iodef);
}
		

sub message {
	my $self = shift;

	# we want to know:
	# origSystem
	# CaseID:
	# EventList:
	# File:
	# Case Timestamp:
	# Estimated Start Timestamp:

	my $details = $self->details();

	my $msg = "\n";

	$msg .= "Rule:\t\t".$self->details->{'name'}."\n";

	my $addr = $details->{'sourceAddress'} || $details->{'destinationAddress'};

	if($details->{'sourceAddress'}){
		$msg .= "Source:\t\t".$details->{'sourceAddress'};
		if(my $host = $details->{'sourceHostName'}){
			$msg .= ' ('.$host.')';
		}
		if(my $sport = $details->{'sourcePort'}){
			my $proto = $details->{'transportProtocol'};
			$msg .= ': '.$proto.'/'.$sport."\n";
		} else { $msg .= "\n"; }
	}
	if($details->{'destinationAddress'}){
		$msg .= "Destination:\t".$details->{'destinationAddress'};
		if(my $host = $details->{'destinationHostName'}){
			$msg .= ' ('.$host.')';
		}
		
		if(my $dport = $details->{'destinationPort'}){
			my $proto = $details->{'transportProtocol'};
			$msg .= ': '.$proto.'/'.$dport."\n";
		} else { $msg .= "\n"; }
	}
	$msg .= "\nStart Time:\t".$details->{'startTime'}." UTC\n";
	$msg .= "End Time:\t".$details->{'endTime'}." UTC\n";

	return $msg unless($self->baseEvents());

	$msg .= "\n\n\n";

	my @sort = sort { $a <=> $b } keys(%{$self->baseEvents()});

	my $table = Text::Table->new('|','Date/Time','|','Type','|','Device','|','Rule','|');

	foreach my $event (@sort){
		
		my $d = $self->baseEvents->{$event}->details();
		$table->load(['|',$d->{'startTime'},'|',$d->{'device'}->{'map'}->{'product'},'|',$d->{'device'}->{'map'}->{'hostName'},'|',$d->{'name'},'|']);
	}

	$msg .= "\n\n".$table;

	$table = Text::Table->new('|','Date/Time','|','Protocol','|','Source','|','Destination','|');

	foreach my $event (@sort){
		my $d = $self->baseEvents->{$event}->details();
		$table->load(['|',$d->{'startTime'},'|', $d->{'transportProtocol'},'|',$d->{'sourceAddress'}.':'.$d->{'sourcePort'},'|', $d->{'destinationAddress'}.':'.$d->{'destinationPort'},'|']);
	}

	$msg .= "\n\n".$table;

	$table = Text::Table->new('|','Date/Time','|','Protocol','|','Source','|','Destination','|');

	foreach my $event (@sort){
		my $d = $self->baseEvents->{$event}->details();

		my $src = $d->{'sourceHostName'} || $d->{'sourceAddress'};
		my $dst = $d->{'destinationHostName'} || $d->{'destinationAddress'};

		$table->load(['|',$d->{'startTime'},'|', $d->{'transportProtocol'},'|',$src.':'.$d->{'sourcePort'},'|', $dst.':'.$d->{'destinationPort'},'|']);
	}

	$msg .= "\n\n".$table;

	$table = Text::Table->new('|','Date/Time','|','Source Country','|','Source Region','|','Source Location','|','Destination Country','|','Destination Region','|','Destination Area','|');

	foreach my $event (@sort){
		my $d = $self->baseEvents->{$event}->details();

		my $srcC = $d->{'sourceGeo'}->{'map'}->{'countryCode'} || 'NA';
		my $srcL = $d->{'sourceGeo'}->{'map'}->{'locationInfo'} || 'NA';
		my $srcR = $d->{'sourceGeo'}->{'map'}->{'regionCode'} || 'NA';

		my $dstC = $d->{'destinationGeo'}->{'map'}->{'countryCode'} || 'NA';
		my $dstL = $d->{'destinationGeo'}->{'map'}->{'locationInfo'} || 'NA';
		my $dstR = $d->{'destinationGeo'}->{'map'}->{'regionCode'} || 'NA';

		$table->load(['|',$d->{'startTime'},'|', $srcC,'|',$srcR,'|',$srcL,'|',$dstC,'|', $dstR, '|',$dstL,'|']);
	}

	return $msg."\n\n".$table;
}

1;

__END__
